package lyf.framework.beans;

import lyf.framework.web.mvc.Controller;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * bean工厂
 */
public class BeanFactory {
	/**
	 * 此处可能并行处理，因此需要使用ConcurrentHashMap
	 */
	private static Map<Class<?>, Object> classToBean = new ConcurrentHashMap<>();

	public static Object getBean(Class<?> cls) {
		return classToBean.get(cls);
	}

	/**
	 * bean加载
	 */
	public static void initBean(List<Class<?>> classList) throws Exception {
		List<Class<?>> toCreate = new ArrayList<>(classList);
		while (toCreate.size() != 0) {
			int size = toCreate.size();
			for (int i = 0; i < toCreate.size(); i++) {
				 if (finishCreate(toCreate.get(i))) {
				 	toCreate.remove(i);
				 }
			}

			if (toCreate.size() == size) {
				throw new Exception("循环依赖, 无法完成初始化");
			}
		}
	}

	/**
	 * 进行bean注册
	 */
	private static boolean finishCreate(Class<?> cls) throws IllegalAccessException, InstantiationException {
		// 没有添加注解的类不需要处理
		if (!cls.isAnnotationPresent(Component.class) && !cls.isAnnotationPresent(Controller.class)) {
			return true;
		} else {
			Object instance = cls.newInstance();
			for (Field field : cls.getDeclaredFields()) {
				if (field.isAnnotationPresent(AutoWired.class)) {
					// 依赖的bean已经实例化了就设置并实例化，没有就不实例化
					Object bean = BeanFactory.getBean(field.getType());
					if (bean == null) {
						return false;
					}
					field.setAccessible(true);
					field.set(instance, bean);
				}
			}
			// 把实例化后的bean注入工厂中
			classToBean.put(cls, instance);
			return true;
		}
	}
}
